#include "bridge.h"
#include <QDebug>
#include <QFile>
#include <QTextCodec>

IBridge* getBridge()
{
	IBridge* p_bridge = new Bridge();
	return p_bridge;
}

Bridge::Bridge()
{
	_path="adb/adb.exe"; 
	_command.clear();
	_selectedDevice.clear();  
}

Bridge::~Bridge()
{
	killServer();
}

//read output data
void Bridge::readOutput(QProcess* procces)
{
	_data.clear();
	_error.clear();
	// Continue reading the data until EOF reached
	while(procces->waitForReadyRead())
	{
		_data.append(procces->readAllStandardOutput());
		_error.append(procces->readAllStandardError());
	}
}

//start adb server
void Bridge::startServer()
{
	killServer();
	_command=_path+" start-server";
    _process.start(_command);
	readOutput(&_process);
}
	
//kill adb server
void Bridge::killServer()
{
	_command=_path+" kill-server";
    _process.start(_command);
	readOutput(&_process);
}

//return list of unparsed strings with adb-name and model of device
QString Bridge::getDevices()
{
	_command=_path+" devices";
    _process.start(_command);
	readOutput(&_process);
	return _data;
}

//method sets name of the selected device at the moment
void Bridge::setSelectedDevice(QString s)
{
	_selectedDevice=s;
}

//save screenshot to path
void Bridge::getScreenshot(QString str)
{
	qDebug() << "filepath: "<<str;
	QProcess process;
	if (!_selectedDevice.isEmpty())
	{
		_command=_path+" -s "+_selectedDevice+" shell screencap -p";
		process.start(_command);
	}

	QByteArray* image = new QByteArray();

	bool result=false;
	// Continue reading the data until EOF reached
	while(process.waitForReadyRead())
	{
		image->append(process.readAllStandardOutput());
	}

	qDebug()<<"Size 1: "<<image->length();
	image->replace("\r\r\n", "\n");
	qDebug()<<"Size 2: "<<image->length();

	QFile outFile(str);
	if (!outFile.open(QIODevice::WriteOnly))
	{
		qDebug() << "Error opening a file\n";
	}
	else
	{
		outFile.write(*image);
		outFile.close();
		result=true;
	}

	delete image;
	//result;
}

//return file system
QString Bridge::getFileSystem(QString s)
{
	_command=_path+" -s "+_selectedDevice+" shell ls -la \""+s+"\"";
	_process.start(formatToUTF8(_command));

	readOutput(&_process);
	return _data;
}


//method to create new Folder
bool Bridge::newFolder(QString name, QString path)
{
	_command = _path + " -s " + _selectedDevice + " shell mkdir \"" + path + name +"\"";
	_process.start(formatToUTF8(_command));

	readOutput(&_process);
	qDebug()<<"new_folder"<<_data;
	qDebug() <<"error:"<< _error;
	return _data.isEmpty()? true:false;
}

//method to remove selected item(folder,file)
bool Bridge::Delete(QString path, QString name)
{
	_command = _path + " -s " + _selectedDevice + " shell rm -r  \"" + path + name +"\"";
	_process.start(formatToUTF8(_command));
	readOutput(&_process);
	qDebug()<< "command "<< _command;
	qDebug()<<"delete_folder"<<_data;
	return _data.isEmpty()? true:false;
}

//method which provide installing .apk file from selected directory(PC or device)
bool Bridge::Install(QString cmd)
{
	QProcess *proc = new QProcess();
	_command = _path + " -s " + _selectedDevice + cmd ;
	proc->start(formatToUTF8(_command));
	readOutput(proc);
	qDebug() <<"install"<< _data;
	if(proc)
		delete proc;
	return _data.isEmpty()? false:true;
}

//copy file to device
bool Bridge::pushToDevice(QString filePath,QString devicePath)
{
	QProcess *proc = new QProcess();
	int index = filePath.lastIndexOf("/")+1;
	QString name = filePath.right(filePath.length()-index);
	qDebug()<<"name:"<<name;
	QStringList arguments;
	arguments<<"-s"<<_selectedDevice<<"push";
	arguments.append(filePath);
	QString temp = devicePath + name;
	arguments.append(formatToUTF8(temp));
	qDebug()<<arguments;
	
	proc->start(_path,arguments);
	readOutput(proc);
	
	qDebug() <<"error:"<< _error;
	bool res = !_error.contains("bytes in");
	if(proc)
		delete proc;
	return res;
}

//copy file from device
bool Bridge::pullFromDevice(QString filePathOnDevice,QString pullPath)
{
	QProcess *proc = new QProcess();
	pullPath.replace("/","\\");
	int index = filePathOnDevice.lastIndexOf("/")+1;
	QString name = filePathOnDevice.right(filePathOnDevice.length()-index);
	qDebug()<<"name:"<<name;

	QStringList arguments;
	arguments<<"-s"<<_selectedDevice<<"pull";
	arguments.append(formatToUTF8(filePathOnDevice));

	qDebug()<<pullPath;
	QString temp;
	if (pullPath.endsWith("\\")) 
		temp = pullPath + name;
	else
		temp = pullPath + "\\" + name;
	qDebug()<<temp;
	arguments.append(temp);
	qDebug()<<arguments;

	proc->start(_path,arguments);
	readOutput(proc);
	
	qDebug() <<"error:"<< _error;
	bool res = !_error.contains("bytes in");
	if(proc)
		delete proc;
	return res;	
}

//move or copy files and dirs
bool Bridge::moveFiles(QStringList sourcePath,QString destinationPath,bool isCopy)
{
	
	QString fileSystemPath = sourcePath.first();
	if (fileSystemPath != destinationPath)
	{	
		bool res = true;
		for (int i=1;i<sourcePath.count();i++)
		{
			QStringList arguments;
			arguments<<"-s"<<_selectedDevice<<"shell";
	
			if (isCopy)
				arguments<<"cp"<<"-R"<<"-f";//<<"-p";
			else
				arguments<<"mv";

			QString temp = fileSystemPath + sourcePath[i];
			arguments.append(formatToUTF8(temp));
			arguments.append(formatToUTF8(destinationPath));

			qDebug()<<arguments;
			_process.start(_path,arguments);
			readOutput(&_process);
			if (!_data.isEmpty()) res=false;
		}
		return res;
	}
	else
		return 0;
}

bool Bridge::makeBackup(QString str)
{
	QProcess* process = new QProcess();
	_command = _path + " -s " + _selectedDevice + " backup " + str;
	
	process->start(formatToUTF8(_command));
	
	readOutput(process);
	if(process)
		delete process;
	return _data.isEmpty()? false:true;
}

bool Bridge::restoreBackup(QString file)
{
	QProcess *proc = new QProcess();
	_command = _path + " -s " + _selectedDevice + " restore \"" + file + "\"";
	proc->start(formatToUTF8(_command));

	readOutput(proc);
	if(proc)
		delete proc;
	return _data.isEmpty()? false:true;
}

//This method providing to use UTF8 codec
QString Bridge::formatToUTF8(QString src)
{
	QTextCodec *codec = QTextCodec::codecForName("CP1251");
	QString final = codec->toUnicode(src.toUtf8());
	return final;
}

QString Bridge::getDevicesProps(QString device)
{
	_command = _path + " -s " + device + " shell getprop";
	_process.start(_command);
	readOutput(&_process);	
	return _data;
}

bool Bridge::Rename(QString str)
{
	_command = _path + " -s " + _selectedDevice + " shell mv "+str;	
	_process.start(formatToUTF8(_command));
	readOutput(&_process);
	qDebug()<<"rename:"<<_data;
	qDebug() <<"error:"<< _error;
	return _data.isEmpty()? true:false;
}

